package cn.edu.xjtu.android.emoji_warfare_android.game;

import java.util.ArrayList;

import android.os.Message;
import cn.edu.xjtu.android.emoji_warfare_android.MainActivity;
import cn.edu.xjtu.android.emoji_warfare_android.engine.BaseEngine;
import cn.edu.xjtu.android.emoji_warfare_android.engine.Item;
import cn.edu.xjtu.android.emoji_warfare_android.engine.entity.Entity;
import cn.edu.xjtu.android.emoji_warfare_android.engine.worker.CollideWorker.CollideListener;
import cn.edu.xjtu.android.emoji_warfare_android.engine.worker.DelayedOperation;
import cn.edu.xjtu.android.emoji_warfare_android.game.hero.Enemy;
import cn.edu.xjtu.android.emoji_warfare_android.game.hero.Player;
import cn.edu.xjtu.android.emoji_warfare_android.game.item.SheildItem;
import cn.edu.xjtu.android.emoji_warfare_android.game.item.WeaponItem;
import cn.edu.xjtu.android.emoji_warfare_android.game.widget.ScoreBar;
import cn.edu.xjtu.android.emoji_warfare_android.music.Musics;

/**
 * 主引擎
 * 
 * @author bill
 *
 */
public class Engine extends BaseEngine {

    public final ArrayList<Controller> mControllers;
    public final LayerManager Layers;
    public EnemyLoader el;
    EnemyController ec;
    AutoShoot as;
    public ScoreBar sb;
    public boolean hasLaser;
    private int rate;

    /**
     * 创建游戏
     * 
     * @param width
     *            屏幕宽度
     * @param height
     *            屏幕高度
     * @param margin
     *            物理引擎扩展边界
     */
    public Engine(int width, int height, int margin) {
        super(width, height, margin);
        Engine.instance = this;
        Layers = new LayerManager(Render);
        mControllers = new ArrayList<Controller>();
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        el = new EnemyLoader(this);
        ec = new EnemyController(this, el);
        as = new AutoShoot(this.getDefaultController().player, 135);
        sb = new ScoreBar(this.getDefaultController().player);

        this.Delayed.add(el);
        this.Delayed.add(ec);
        this.Delayed.add(as);
        this.Layers.Widgets.add(sb);

        Render.getScreenBoundary().setBackground(Config.Back.background);
        this.Layers.Background.add(Render.getScreenBoundary());

        // 玩家的子弹打到敌人
        Collide.addListener(Layers.PlayerBullet, Layers.Enemy, new CollideListener() {
            @Override
            public void onCollide(Entity sbj, Entity obj) {
                Enemy e = (Enemy) obj;

                if (sbj instanceof Bullet) {
                    // 普通子弹伤害
                    Bullet b = (Bullet) sbj;
                    e.inDamage = true;
                    e.hp -= b.atk;
                    b.basePoint.x = -1000;
                    b.basePoint.y = -1000;

                } else if (sbj instanceof Laser) {

                    // 激光伤害
                    if (e.lasetDamageCount++ == 0) {
                        e.inDamage = true;
                        e.hp -= (int) (Engine.this.getDefaultController().player.level / 2 + 3);
                    }

                    // 每5次造成一次伤害
                    e.lasetDamageCount %= 5;
                }

                // 计算经验加成
                Player player = Engine.this.getDefaultController().player;
                player.exp += e.level;
                int level = (int) Math.log(player.exp + 1);
                if (level != player.level) {
                    player.hp = (int) Math.log(level + 5) * 5;
                    player.level = level;
                }
                player.resetATK();

                Engine.this.sb.score = player.exp * rate;
            }
        });

        // 玩家捡起物品
        Collide.addListener(Layers.Player, Layers.Item, new CollideListener() {
            @Override
            public void onCollide(Entity sbj, Entity obj) {
                if (sbj instanceof Sheild) {
                    return;
                }

                // 捡拾物品
                Player p = (Player) sbj;
                Item i = (Item) obj;

                // 设置玩家的武器
                if (i instanceof WeaponItem) {
                    WeaponItem wi = (WeaponItem) i;
                    p.setWeapon(wi.getWeapon());
                    p.setWeaponOverTime(clock() + 15 * 1000);
                    p.addATK();

                    if (wi.getWeapon() == 4) {
                        // 如果是激光则启动启光
                        p.openLaser();
                    }

                    // 记录Item个数减少

                } else if (i instanceof SheildItem) {

                    // 开盾
                    Engine.this.getDefaultController().player.openSheild(10000);
                }

                i.basePoint.x = -1000;
            }
        });

        // 玩家受到伤害
        CollideListener damageCollideListener = new CollideListener() {
            @Override
            public void onCollide(Entity sbj, Entity obj) {
                if (obj instanceof Sheild) {
                    // 盾牌防御
                    if (sbj instanceof Bullet) {
                        Bullet b = (Bullet) sbj;
                        b.basePoint.x = -1000;
                    } else if (sbj instanceof Enemy) {
                        Enemy e = (Enemy) sbj;
                        e.inDamage = true;
                        e.hp -= 1;
                    }
                } else if (obj instanceof Player) {
                    Player p = (Player) obj;
                    if (p.canDamage) {
                        if (sbj instanceof Bullet) {
                            Bullet b = (Bullet) sbj;
                            p.inDamage = true;
                            p.hp -= b.atk;
                            checkDeath(p);
                            p.setWeaponOverTime(clock());
                            b.basePoint.x = -1000;
                        } else if (sbj instanceof Enemy) {
                            Enemy e = (Enemy) sbj;
                            p.inDamage = true;
                            p.hp -= 1;
                            e.inDamage = true;
                            e.hp -= p.level * 3;
                            checkDeath(p);
                            p.setWeaponOverTime(clock());
                        }
                    }
                }
            }

            private void checkDeath(Player p) {
                // 死亡检查
                if (p.hp <= 0) {
                    MainActivity.instance.canControl = false;
                    float s = p.basePoint.y;
                    p.basePoint.y = 1920 + Config.Hero.radius;
                    // 关闭激光
                    p.stopLaser();
                    Engine.this.sb.life--;
                    if (Engine.this.sb.life >= 0) {
                        Engine.this.as.interrupt();

                        // 开启盾牌
                        Engine.this.getDefaultController().player.openSheild(5000);
                        Engine.this.Delayed.add(new DelayedOperation() {

                            @Override
                            public boolean run() {
                                this.setDelayMillis(3);
                                Player p = Engine.this.getDefaultController().player;

                                // 移动玩家
                                p.basePoint.y -= 1f;
                                if (p.basePoint.y < 1500) {

                                    // 回血，恢复控制并恢复射击
                                    Engine.this.as.resume();
                                    Engine.this.getDefaultController().player.hp = (int) Math
                                            .sqrt(Engine.this.getDefaultController().player.level + 5) * 5;
                                    MainActivity.instance.canControl = true;

                                    return true;
                                } else {
                                    return false;
                                }
                            }

                        });

                    } else {
                        p.basePoint.y = s;
                        MainActivity.instance.canControl = false;
                        Engine.this.as.interrupt();
                        Message msg = new Message();
                        msg.what = 999;
                        msg.setTarget(MainActivity.instance.mHandler);
                        msg.sendToTarget();
                        Engine.this.pause();
                    }

                }
            }
        };

        Collide.addListener(Layers.EnemyBullet, Layers.Player, damageCollideListener);

        Collide.addListener(Layers.Enemy, Layers.Player, damageCollideListener);

        rate = 1;
    }

    /**
     * 设置生命数
     * 
     * @param life
     *            生命数
     */
    public void setLife(int life) {
        sb.life = life;
    }

    /**
     * 设置模式
     * 
     * @param mode
     *            模式
     */
    public void setMode(String mode) {
        if (mode == null) {
            mode = "None";
        }
        sb.mode = mode;

        // 设置得分倍率
        if (mode.equals("极限")) {
            rate = 30;
        } else if (mode.equals("困难")) {
            rate = 10;
        } else if (mode.equals("普通")) {
            rate = 6;
        } else if (mode.equals("简单")) {
            rate = 3;
        }
    }

    /**
     * 添加玩家<br>
     * 未来可能支持多人模式
     * 
     * @return 玩家编号
     */
    public int addPlayer() {
        Player p = new Player(this);
        Controller c = new Controller(p);
        Layers.Player.add(p);

        mControllers.add(c);
        return mControllers.size() - 1;
    }

    /**
     * 获取主控制器
     * 
     * @return 主控制器
     */
    public Controller getDefaultController() {
        if (this.mControllers.size() == 0) {
            this.addPlayer();
        }
        return mControllers.get(0);
    }

    public void addPlayerBullet(Bullet b) {
        Move.add(b);
        Layers.PlayerBullet.add(b);
    }

    public void addEnemyBullet(Bullet b) {
        Move.add(b);
        Layers.EnemyBullet.add(b);
    }

    public void addPlayerBullets(Bullet[] bs) {
        for (Bullet b : bs) {
            addPlayerBullet(b);
        }
    }

    public void addEnemyBullets(Bullet[] bs) {
        for (Bullet b : bs) {
            addEnemyBullet(b);
        }
    }

    public static Engine instance;

    @Override
    public void resume() {
        Musics.getInstance().start();
        super.resume();
    }

    @Override
    public void pause() {
        Musics.getInstance().pause();
        super.pause();
    }

}
